package com.itheima.tliasbackend.aspect;

import com.itheima.tliasbackend.mapper.OperateLogMapper;
import com.itheima.tliasbackend.pojo.OperateLog;
import com.itheima.tliasbackend.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * SysLogAspect
 *
 * @author liliudong
 * @version 1.0
 * @description 系统日志切面类
 * @date 2023/5/26 17:08
 */
@Slf4j
@Component
@Aspect
public class SysLogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;

    @Pointcut("@annotation(com.itheima.tliasbackend.annotation1.SysLog)")
    public void pt() {
    }

    // 操作人ID、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长
    @Around("pt()")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 操作人
        // 1.1 从请求头中获取token
        String token = request.getHeader("token");
        // 1.2 解析token获取token中存储的userId
        Claims claims = JwtUtils.parseJWT(token);
        Integer operateUser = (Integer) claims.get("id");

        // 2. 操作时间
        LocalDateTime operateTime = LocalDateTime.now();

        // 3. 执行目标方法的全类名
        String className = joinPoint.getTarget().getClass().getName();

        // 4. 执行方法名
        String methodName = joinPoint.getSignature().toString();

        // 开始时间
        long start = System.currentTimeMillis();
        Object o = joinPoint.proceed();
        long end = System.currentTimeMillis();
        // 5. 获取入参
        String methodParams = Arrays.toString(joinPoint.getArgs());

        // 6. 返回值
        String returnValue = o.toString();

        // 7. 方法执行时长
        Long costTime = end - start;

        // 8. 构建日志实体
        OperateLog operateLog = new OperateLog();
        operateLog.setOperateUser(operateUser);
        operateLog.setOperateTime(operateTime);
        operateLog.setClassName(className);
        operateLog.setMethodName(methodName);
        operateLog.setMethodParams(methodParams);
        operateLog.setReturnValue(returnValue);
        operateLog.setCostTime(costTime);
        // 9. 将数据写入库中
        operateLogMapper.insert(operateLog);

        return o;
    }
}
